﻿using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using Jinndev;

namespace JinndevEditor {

    public class ReplaceColorEditor : EditorWindow {

        public static void Open() {
            var window = GetWindow<ReplaceColorEditor>("替换颜色");
            window.Show();
        }

        private const int textureLength = 200;

        private Texture2D inputTexture;
        private float threshold = 0.1f;
        private bool overrideSelf = false;
        private bool inverse = false;

        private List<Color> srcColors = new List<Color>();
        private List<Color> destColors = new List<Color>();

        private SerializedProperty prop;

        private void OnEnable() {
            if (srcColors.Count == 0) {
                srcColors.Add(new Color(1, 1, 1, 1));
            }
            if (destColors.Count == 0) {
                destColors.Add(new Color(0, 0, 0, 0));
            }
        }

        private void OnGUI() {
            GUILayout.Space(10);


            // 输入纹理
            inputTexture = EditorGUILayout.ObjectField(inputTexture, typeof(Texture2D), false, GUILayout.Width(textureLength), GUILayout.Height(textureLength)) as Texture2D;
            GUILayout.Space(10);

            for (int i = 0; i < srcColors.Count; i++) {
                EditorGUILayout.BeginHorizontal();
                if (GUILayout.Button("-", GUILayout.Width(30))) {
                    srcColors.RemoveAt(i);
                    destColors.RemoveAt(i);
                    break;
                }
                EditorGUILayout.BeginVertical();
                srcColors[i] = EditorGUILayout.ColorField("源颜色", srcColors[i], GUILayout.Width(300));
                destColors[i] = EditorGUILayout.ColorField("目标颜色", destColors[i], GUILayout.Width(300));
                EditorGUILayout.EndVertical();
                EditorGUILayout.EndHorizontal();
            }
            if (GUILayout.Button("+", GUILayout.Width(30))) {
                srcColors.Add(new Color(1, 1, 1, 1));
                destColors.Add(new Color(0, 0, 0, 0));
            }

            GUILayout.Space(10);

            EditorGUILayout.BeginHorizontal();
            threshold = EditorGUILayout.Slider("阈值", threshold, 0, 1f, GUILayout.Width(300));
            EditorGUILayout.LabelField($"{threshold * 255}/255");
            EditorGUILayout.EndHorizontal();

            inverse = EditorGUILayout.Toggle("取反", inverse, GUILayout.Width(300));
            overrideSelf = EditorGUILayout.Toggle("覆盖原图", overrideSelf, GUILayout.Width(300));


            GUILayout.Space(10);
            GUI.enabled = inputTexture != null && srcColors.Count > 0;
            if (GUILayout.Button("生成", GUILayout.Width(200))) {
                Generate();
            }
            GUI.enabled = true;
            GUILayout.Space(10);
        }

        private void Generate() {
            bool readable = CommonEditorUtil.SetReadable(inputTexture, true);
            var pixels = inputTexture.GetPixels();
            CommonEditorUtil.SetReadable(inputTexture, readable);
            long changed = 0;

            for (int i = 0; i < pixels.Length; i++) {
                if (EditorUtility.DisplayCancelableProgressBar("Generate", $"{i} / {pixels.Length}", (float)i / pixels.Length)) {
                    break;
                }
                Color pixel = pixels[i];
                for (int j = 0; j < srcColors.Count; j++) {
                    bool similar = Approximately(pixel, srcColors[j]);
                    if (similar && !inverse || !similar && inverse) {
                        pixels[i] = destColors[j];
                        changed++;
                        break;
                    }
                }
            }

            Texture2D texture = new Texture2D(inputTexture.width, inputTexture.height);
            texture.SetPixels(pixels);
            texture.Apply();

            byte[] bytes = texture.EncodeToPNG();
            DestroyImmediate(texture);

            string path = AssetDatabase.GetAssetPath(inputTexture);
            if (!overrideSelf) {
                string name = Path.GetFileNameWithoutExtension(path);
                path = CommonUtil.ReplaceFileName(path, name + "_generate.png");
            }
            File.WriteAllBytes(path, bytes);

            AssetDatabase.Refresh();

            EditorUtility.ClearProgressBar();
        }

        private bool Approximately(Color a, Color b) {
            return CommonUtil.Approximately(a.r, b.r, threshold) && CommonUtil.Approximately(a.g, b.g, threshold)
                && CommonUtil.Approximately(a.b, b.b, threshold) && CommonUtil.Approximately(a.a, b.a, threshold);
        }

    }

}
